﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ImageProcessing.Forms
{
    public partial class Morphology : Form
    {
        /// <summary>
        /// Mask height
        /// </summary>
        private int maskHeigth = 0;

        /// <summary>
        /// Mask width
        /// </summary>
        private int maskwidth = 0;

        /// <summary>
        /// Mask array
        /// </summary>
        private byte[,] mask;

        /// <summary>
        /// Original image
        /// </summary>
        private ImageStructure[,] orginal;

        /// <summary>
        /// Boolean to check state of mask
        /// </summary>
        private bool stateMask = false;

        /// <summary>
        /// center point
        /// </summary>
        private Point center;

        /// <summary>
        /// count center
        /// </summary>
        private int countcenter = 0;

        /// <summary>
        /// for new result
        /// </summary>
        private DImage resultBitmap = new DImage();

        public Morphology()
        {
            InitializeComponent();
            try
            {
                Main.ImageList[Main.CurrImage].BackupImageArray();
                this.orginal = ResizeImage.BicubicResize(this.PcbOriginal.Width, this.PcbOriginal.Height, Main.ImageList[Main.CurrImage].ImageStructArray, 2);
                this.PcbOriginal.Image = Operations.DisplayMatrix(Main.ImageList[Main.CurrImage].ImageStructArray);
                this.PcbNewImage.Image = Operations.DisplayMatrix(Main.ImageList[Main.CurrImage].ImageStructArray);
                this.CmbProcess.Items.Add("Dilation");
                this.CmbProcess.Items.Add("Erosion");
                this.CmbProcess.SelectedIndex = 1;
                center.X = -1;
                center.Y = -1;
                this.CBox_Shape.Items.Add("Left triangle");
                this.CBox_Shape.Items.Add("Rigth triangle");
                this.CBox_Shape.Items.Add("square");
                this.CBox_Shape.Items.Add("Circle");
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        /// <summary>
        /// Handles the Click event of the BtnLoadMask control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void BtnLoadMask_Click(object sender, EventArgs e)
        {
            string fileName;
            OpenFileDialog browseFile = new OpenFileDialog();

            if (browseFile.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            try
            {
                fileName = browseFile.FileName;
                this.mask = NeighborhoodOperations.LoadMakByte(fileName);

                this.dataGridMask.RowCount = this.mask.GetLength(0);
                this.dataGridMask.ColumnCount = this.mask.GetLength(1);
                for (int i = 0; i < this.dataGridMask.RowCount; i++)
                {
                    for (int j = 0; j < this.dataGridMask.ColumnCount; j++)
                    {
                        this.dataGridMask.Rows[i].Cells[j].Value = (int)this.mask[i, j];
                        this.SetCellColor(i, j);
                    }
                }

                if (this.dataGridMask.RowCount > 0 && this.dataGridMask.ColumnCount > 0)
                {
                    this.stateMask = true;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
                MessageBox.Show("Error opening file", "File Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

        /// <summary>
        /// Handles the Click event of the BtnSaveMask control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void BtnSaveMask_Click(object sender, EventArgs e)
        {
            if (!this.stateMask)
            {
                MessageBox.Show("Invalde width hiegth");
                return;
            }

            string fileName;
            SaveFileDialog saveeFile = new SaveFileDialog();

            if (saveeFile.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            try
            {
                fileName = saveeFile.FileName + ".txt";
                for (int i = 0; i < this.dataGridMask.RowCount; i++)
                {
                    for (int j = 0; j < this.dataGridMask.ColumnCount; j++)
                    {
                        this.mask[i, j] = Convert.ToByte(this.dataGridMask.Rows[i].Cells[j].Value);

                    }
                }

                NeighborhoodOperations.SaveMaskByte(this.mask, fileName);
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
                MessageBox.Show("Error opening file", "File Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

        /// <summary>
        /// Handles the TextChanged event of the TxtHiegth control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void TxtHiegth_TextChanged(object sender, EventArgs e)
        {
            try
            {
                int heigth;
                bool isNum = int.TryParse(this.TxtHiegth.Text, out heigth);

                if (isNum)
                {
                    this.errorProviderHiegth.SetError(this.TxtHiegth, string.Empty);
                    this.maskHeigth = heigth;
                    if (this.maskwidth != 0)
                    {
                        this.dataGridMask.RowCount = this.maskHeigth;
                        this.dataGridMask.ColumnCount = this.maskwidth;
                        this.stateMask = true;
                        this.ReSetDataGridView();
                    }
                }
                else if (this.TxtHiegth.Text == string.Empty)
                {
                    this.errorProviderHiegth.SetError(this.TxtHiegth, string.Empty);
                    this.stateMask = false;
                }
                else
                {
                    this.errorProviderHiegth.SetError(this.TxtHiegth, "invalde number");
                    this.stateMask = false;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        /// <summary>
        /// Handles the TextChanged event of the TxtWidth control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void TxtWidth_TextChanged(object sender, EventArgs e)
        {
            try
            {
                int width;
                bool isNum = int.TryParse(this.TxtWidth.Text, out width);

                if (isNum)
                {
                    this.errorProviderWidth.SetError(this.TxtWidth, string.Empty);
                    this.maskwidth = width;
                    if (this.maskHeigth != 0)
                    {
                        this.dataGridMask.RowCount = this.maskHeigth;
                        this.dataGridMask.ColumnCount = this.maskwidth;
                        this.stateMask = true;
                        this.ReSetDataGridView();
                    }
                }
                else if (this.TxtWidth.Text == string.Empty)
                {
                    this.errorProviderWidth.SetError(this.TxtWidth, string.Empty);
                    this.stateMask = false;
                }
                else
                {
                    this.errorProviderWidth.SetError(this.TxtWidth, "Invalid number");
                    this.stateMask = false;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the CmbProcess control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void CmbProcess_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void BtnRunMask_Click(object sender, EventArgs e)
        {
            if (countcenter != 1)
            {
                MessageBox.Show("Please Select Center");
                return;
            }

            try
            {
                if (this.stateMask)
                {
                    this.mask = new byte[this.dataGridMask.RowCount, this.dataGridMask.ColumnCount];
                    for (int i = 0; i < this.dataGridMask.RowCount; i++)
                    {
                        for (int j = 0; j < this.dataGridMask.ColumnCount; j++)
                        {
                            this.mask[i, j] = Convert.ToByte(this.dataGridMask.Rows[i].Cells[j].Value);
                        }
                    }
                }
                else
                {
                    return;
                }

                switch (this.CmbProcess.SelectedIndex)
                {
                    case 0:
                        this.resultBitmap.ImageBitmap = Operations.DisplayMatrix(MorphologyOperations.Dilation(Main.ImageList[Main.CurrImage].ImageStructArray, this.mask, center));
                        this.PcbNewImage.Image = this.resultBitmap.ImageBitmap;
                        break;
                    case 1:
                        this.resultBitmap.ImageBitmap = Operations.DisplayMatrix(MorphologyOperations.Erosion(Main.ImageList[Main.CurrImage].ImageStructArray, this.mask, center));
                        this.PcbNewImage.Image = this.resultBitmap.ImageBitmap;
                        break;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }

          //  switch (this.CmbProcess.SelectedIndex)
          //  {
              //  case 0:
                    //this.PcbNewImage.Image = Operations.DisplayMatrix(MorphologyOperations.Dilation(Main.ImageList[Main.CurrImage].ImageStructArray, this.mask, center));
                    //this.PcbNewImage.Image = MorphologyOperations.DilationFast(Main.ImageList[Main.CurrImage].ImageBitmap, this.mask, center);
                    // MorphologyOperations.ReflectSharp(this.mask);
                    // this.PcbNewImage.Image = MorphologyOperations.ThresholdSharp(Main.ImageList[Main.CurrImage].ImageBitmap, 128);
                    //byte[] m = {1,1,1,1,1,1,1,1,1};
                    //this.PcbNewImage.Image = MorphologyOperations.DilationFastSharp(Main.ImageList[Main.CurrImage].ImageBitmap,m,new Point(0,0));
                  //  break;
               // case 1:
                   // this.PcbNewImage.Image = Operations.DisplayMatrix(MorphologyOperations.Erosion(Main.ImageList[Main.CurrImage].ImageStructArray, this.mask, center));
                    //this.PcbNewImage.Image = MorphologyOperations.ErosionFast(Main.ImageList[Main.CurrImage].ImageBitmap, this.mask, center);
                    // this.PcbNewImage.Image = MorphologyOperations.ThresholdSharp(Main.ImageList[Main.CurrImage].ImageBitmap, 128);
                   // break;
           // }
        }

        /// <summary>
        /// Handles the Click event of the BtnCancel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void BtnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Handles the Click event of the BtnSetMask control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void BtnSetMask_Click(object sender, EventArgs e)
        {
            this.SetDataGridView();
        }

        /// <summary>
        /// Sets the data grid view.
        /// </summary>
        private void SetDataGridView()
        {
            try
            {
                if (this.stateMask)
                {
                    this.mask = new byte[this.dataGridMask.RowCount, this.dataGridMask.ColumnCount];
                    for (int i = 0; i < this.dataGridMask.RowCount; i++)
                    {
                        for (int j = 0; j < this.dataGridMask.ColumnCount; j++)
                        {
                            this.mask[i, j] = 1;
                            this.dataGridMask.Rows[i].Cells[j].Value = 1;
                            if (i == this.center.X && j == this.center.Y)
                                continue;

                            this.SetCellColor(i, j);
                        }
                    }
                }
                else
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        /// <summary>
        /// Handles the Click event of the BtnReSetMask control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void BtnReSetMask_Click(object sender, EventArgs e)
        {
            this.ReSetDataGridView();
        }

        /// <summary>
        /// Res the set data grid view.
        /// </summary>
        private void ReSetDataGridView()
        {
            try
            {
                if (this.stateMask)
                {
                    this.mask = new byte[this.dataGridMask.RowCount, this.dataGridMask.ColumnCount];
                    for (int i = 0; i < this.dataGridMask.RowCount; i++)
                    {
                        for (int j = 0; j < this.dataGridMask.ColumnCount; j++)
                        {
                            this.mask[i, j] = 0;
                            this.dataGridMask.Rows[i].Cells[j].Value = 0;
                            this.dataGridMask.Rows[i].Height = 40;
                            this.dataGridMask.Columns[j].Width = 40;

                            if (i == this.center.X && j == this.center.Y)
                                continue;

                            this.SetCellColor(i, j);
                        }
                    }

                }
                else
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        private void BtnOk_Click(object sender, EventArgs e)
        {
            try
            {
                Main.ImageList[Main.CurrImage].UpdateImage(Operations.ConvertBitmapToStructure(this.resultBitmap.ImageBitmap));
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
            this.Close();
        }

        /// <summary>
        /// Handles the CellContentClick event of the dataGridMask control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.DataGridViewCellEventArgs"/> instance containing the event data.</param>
        private void dataGridMask_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void dataGridMask_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            this.ChangeCellValue(e.RowIndex, e.ColumnIndex);

            if (e.RowIndex == this.center.X && e.ColumnIndex == this.center.Y)
            {
                DataGridViewCellStyle CellStyle = new DataGridViewCellStyle();
                CellStyle.BackColor = Color.Red;
                dataGridMask.Rows[e.RowIndex].Cells[e.ColumnIndex].Style = CellStyle;
                dataGridMask.DefaultCellStyle.SelectionBackColor = CellStyle.BackColor;
                return;
            }
            this.SetCellColor(e.RowIndex, e.ColumnIndex);
        }

        /// <summary>
        /// Changes the cell value.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        private void ChangeCellValue(int x, int y)
        {
            try
            {
                if ((int)dataGridMask.Rows[x].Cells[y].Value == 1)
                {
                    dataGridMask.Rows[x].Cells[y].Value = 0;
                }
                else
                {
                    dataGridMask.Rows[x].Cells[y].Value = 1;
                }
            }
            catch (Exception exp)
            {
                Logger.LogException(exp);

            }

        }


        /// <summary>
        /// Changes the color of the cell.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        private void SetCellColor(int x, int y)
        {
            try
            {
                if (x == center.X && y == center.Y)
                {
                    //DataGridViewCellStyle CellStyle = new DataGridViewCellStyle();
                    //CellStyle.BackColor = Color.Red;
                    //dataGridMask.DefaultCellStyle.SelectionBackColor = CellStyle.BackColor;
                    return;
                }

                if ((int)dataGridMask.Rows[x].Cells[y].Value == 1)
                {
                    DataGridViewCellStyle CellStyle = new DataGridViewCellStyle();
                    CellStyle.BackColor = Color.HotPink;
                    dataGridMask.Rows[x].Cells[y].Style = CellStyle;
                    dataGridMask.DefaultCellStyle.SelectionBackColor = CellStyle.BackColor;
                }
                else
                {
                    DataGridViewCellStyle CellStyle = new DataGridViewCellStyle();
                    CellStyle.BackColor = Color.Gold;
                    dataGridMask.Rows[x].Cells[y].Style = CellStyle;
                    dataGridMask.DefaultCellStyle.SelectionBackColor = CellStyle.BackColor;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        private void dataGridMask_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                if (center.X == e.RowIndex && center.Y == e.ColumnIndex)
                {
                    center.X = -1;
                    center.Y = -1;
                    this.SetCellColor(e.RowIndex, e.ColumnIndex);
                    this.countcenter--;
                    return;
                }

                this.countcenter++;
                if (countcenter == 1)
                {
                    this.center.X = e.RowIndex;
                    this.center.Y = e.ColumnIndex;
                    this.SetCellColor(e.RowIndex, e.ColumnIndex);
                    DataGridViewCellStyle CellStyle = new DataGridViewCellStyle();
                    CellStyle.BackColor = Color.Red;
                    dataGridMask.Rows[e.RowIndex].Cells[e.ColumnIndex].Style = CellStyle;
                    dataGridMask.DefaultCellStyle.SelectionBackColor = CellStyle.BackColor;
                }
                else
                {
                    MessageBox.Show(" error more then  one center");

                    this.countcenter--;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        private void dataGridMask_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e)
        {

        }

        private void dataGridMask_CellMouseLeave(object sender, DataGridViewCellEventArgs e)
        {
        }

        private void dataGridMask_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
        {

        }

        private void dataGridMask_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
        }

        private void dataGridMask_CellLeave(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void dataGridMask_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                if (checkBoxFreeHand.Checked)
                {
                    this.ChangeCellValue(e.RowIndex, e.ColumnIndex);
                    if (e.RowIndex == center.X && e.ColumnIndex == center.Y)
                    {
                        //DataGridViewCellStyle CellStyle = new DataGridViewCellStyle();
                        //CellStyle.BackColor = Color.Red;
                        //dataGridMask.DefaultCellStyle.SelectionBackColor = CellStyle.BackColor;
                        return;
                    }
                    this.SetCellColor(e.RowIndex, e.ColumnIndex);
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        private void dataGridMask_SelectionChanged(object sender, EventArgs e)
        {

        }

        private void groupBox6_Enter(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// Cells the value invers.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        private byte CellValueInvers(int x, int y)
        {
            try
            {
                if ((int)this.dataGridMask.Rows[x].Cells[y].Value == 0)
                {
                    this.dataGridMask.Rows[x].Cells[y].Value = 1;
                    this.SetCellColor(x, y);
                    return 1;
                }
                else
                {
                    this.dataGridMask.Rows[x].Cells[y].Value = 0;
                    this.SetCellColor(x, y);
                    return 0;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
                return 0;
            }
        }

        /// <summary>
        /// Handles the CheckedChanged event of the checkBox1 control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                if (this.stateMask)
                {
                    this.mask = new byte[this.dataGridMask.RowCount, this.dataGridMask.ColumnCount];
                    for (int i = 0; i < this.dataGridMask.RowCount; i++)
                    {
                        for (int j = 0; j < this.dataGridMask.ColumnCount; j++)
                        {

                            this.mask[i, j] = this.CellValueInvers(i, j);

                        }
                    }

                }
                else
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        /// <summary>
        /// Handles the Click event of the Btn_Go control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void Btn_Go_Click(object sender, EventArgs e)
        {
            try
            {
                if (CBox_Shape.SelectedIndex == 0)
                {
                    this.RigthDrawShapes(0);
                }
                else if (CBox_Shape.SelectedIndex == 1)
                {
                    this.RigthDrawShapes(1);
                }
                else if (CBox_Shape.SelectedIndex == 2)
                {
                    this.RigthDrawShapes(2);
                }
                else if (CBox_Shape.SelectedIndex == 3)
                { }
            }
            catch (Exception ex)
            {
                Logger.LogException(ex);
            }
        }

        private void RigthDrawShapes(int type)
        {
            int width = Convert.ToInt32(Txt_Input1.Text);
            if (width > dataGridMask.ColumnCount || width > dataGridMask.RowCount)
            {
                MessageBox.Show("width must be less then mask width");
                return;
            }
            int count = 0, j;
            if (type == 0)
            {
                for (int i = 0; i < width; i++)
                {
                    for (int f = 0; f <= i; f++)
                    {
                        this.dataGridMask.Rows[i].Cells[f].Value = 1;
                        this.SetCellColor(i, f);
                    }
                }

            }
            else if (type == 1)
            {
                for (int i = 0; i < width; i++)
                {
                    count = 0;
                    j = width - 1;
                    while (count <= i)
                    {
                        this.dataGridMask.Rows[i].Cells[j].Value = 1;
                        this.SetCellColor(i, j);
                        j--;
                        count++;
                    }
                }
            }
            else if (type == 2)
            {
                for (int i = 0; i < width; i++)
                {
                    for (j = 0; j < width; j++)
                    {
                        this.dataGridMask.Rows[i].Cells[j].Value = 1;
                        this.SetCellColor(i, j);
                    }
                }
            }

        }

        private void DrawSquare()
        { }

        private void DrawCircle()
        { }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the CBox_Shape control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void CBox_Shape_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (CBox_Shape.SelectedIndex == 0)
            {
                Lbl_Input1.Text = "Width: ";
                Lbl_Input1.Visible = true;
                Txt_Input1.Visible = true;
                //Lbl_Input2.Text = "Height";
                //Lbl_Input2.Visible = true;
                //Txt_Input2.Visible = true;
            }
            else if (CBox_Shape.SelectedIndex == 1)
            {
                Lbl_Input1.Text = "Width: ";
                Lbl_Input1.Visible = true;
                Txt_Input1.Visible = true;
            }
            else if (CBox_Shape.SelectedIndex == 2)
            {
                //square
                Lbl_Input1.Text = "Length: ";
                Lbl_Input1.Visible = true;
                Txt_Input1.Visible = true;
            }
            else if (CBox_Shape.SelectedIndex == 3)
            { }
        }

        private void Morphology_Paint(object sender, PaintEventArgs e)
        {
            //if (center.X != -1 || center.Y == -1)
            //{
            //    DataGridViewCellStyle CellStyle = new DataGridViewCellStyle();
            //    CellStyle.BackColor = Color.Red;
            //    dataGridMask.Rows[center.X].Cells[center.Y].Style = CellStyle;

            //    dataGridMask.DefaultCellStyle.SelectionBackColor = CellStyle.BackColor;
            //}
        }

        /// <summary>
        /// Handles the CheckedChanged event of the CbxReview control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void CbxReview_CheckedChanged(object sender, EventArgs e)
        {

        }
    }
}
